// ============================================================================
//
// Copyright (C) 2006-2007 Dengues
//
// Google Group: http://groups.google.com/group/dengues
// QQ Group: 24885404
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ============================================================================
package org.dengues.designer.ui.process.models;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.dengues.commons.utils.DenguesTextUtil;
import org.dengues.core.DenguesCorePlugin;
import org.dengues.core.module.EMFModule;
import org.dengues.core.process.CompElement;
import org.dengues.core.process.ICompBlockExit;
import org.dengues.core.process.ICompConnection;
import org.dengues.core.process.ICompNode;
import org.dengues.core.process.ICompProcess;
import org.dengues.core.resource.DenguesProject;
import org.dengues.core.resource.DenguesProjectFactory;
import org.dengues.model.project.UserType;
import org.eclipse.emf.common.util.EList;
import org.eclipse.swt.graphics.RGB;
import org.osgi.framework.Constants;

/**
 * Qiang.Zhang.Adolf@gmail.com class global comment. Detailled comment <br/>
 * 
 * $Id: Dengues.epf 1 2006-09-29 17:06:40Z qiang.zhang $
 * 
 */
public class CompProcess extends CompElement implements ICompProcess {

    private static final long serialVersionUID = 12321512132313163L;

    private final DenguesProject denguesProject;

    private final List<CompNode> compNodes;

    private final List<CompElement> elements;

    private final List<CompNote> compNotes;

    private final List<CompBlock> compBlocks;

    private final List<CompNodeLabel> compNodeLabels;

    private final List<ICompConnection> connections;

    public static String PROP_BLOCKS = "compBlocks"; //$NON-NLS-1$

    public static String PROP_BLOCKEXITS = "compBlockExits"; //$NON-NLS-1$

    public static String PROP_NODES = "compNodes"; //$NON-NLS-1$

    public static String PROP_NOTES = "compNotes"; //$NON-NLS-1$

    public static String PROP_NODELABELS = "compNodeLabels"; //$NON-NLS-1$

    private final List<CompConnectionLabel> connectionLabels;

    public static String PROP_CONNECTIONLABEL = "compConnectionLabels"; //$NON-NLS-1$

    public static String PROP_CONNECTIONTRAC = "compConnectionTracs"; //$NON-NLS-1$

    private final List<CompNodeStatus> nodeStatuses;

    public static String PROP_NODE_STATUS = "compNodeStatus"; //$NON-NLS-1$

    private String name;

    private final List<CompConnectionTrac> connectionTracs;

    private String purpose;

    private String author;

    private boolean isBlock;

    private final List<ICompBlockExit> exits;

    /**
     * Qiang.Zhang.Adolf@gmail.com CompProcess constructor comment.
     */
    public CompProcess() {
        compNodes = new ArrayList<CompNode>();
        elements = new ArrayList<CompElement>();
        compNotes = new ArrayList<CompNote>();
        compBlocks = new ArrayList<CompBlock>();
        compNodeLabels = new ArrayList<CompNodeLabel>();
        connections = new ArrayList<ICompConnection>();
        connectionLabels = new ArrayList<CompConnectionLabel>();
        connectionTracs = new ArrayList<CompConnectionTrac>();
        nodeStatuses = new ArrayList<CompNodeStatus>();
        exits = new ArrayList<ICompBlockExit>();

        denguesProject = DenguesProjectFactory.getDenguesProject();
        name = "process";
    }

    public List<CompNode> getCompNodes() {
        return this.compNodes;
    }

    public void addCompNode(CompNode node) {
        compNodes.add(node);
        elements.add(node);
        fireStructureChange(PROP_NODES, compNodes);
    }

    public void removeCompNode(ICompNode node) {
        compNodes.remove(node);
        elements.remove(node);
        fireStructureChange(PROP_NODES, compNodes);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.designer.ui.gef.models.Element#getElementName()
     */
    @Override
    public String getCompName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = DenguesTextUtil.getNotNullString(name);
    }

    /**
     * zx Comment method "isGridEnabled".
     * 
     * @return
     */
    public boolean isGridEnabled() {
        return true;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.core.process.ICompProcess#getCurrentProjectName()
     */
    public String getCurrentProjectName() {
        return denguesProject.getName();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.core.process.ICompProcess#getDescription()
     */
    public String getDescription() {
        String des = ""; //$NON-NLS-1$
        try {
            des = denguesProject.getName();
        } catch (Exception e) {
            des = e.getMessage();
        }
        return des;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.core.process.ICompProcess#getId()
     */
    public String getId() {
        return "ID_" + getName(); //$NON-NLS-1$
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.core.process.ICompProcess#getName()
     */
    public String getName() {
        return getCompName();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.core.process.ICompProcess#getPurpose()
     */
    public String getPurpose() {
        return this.purpose;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.core.process.ICompProcess#getVersion()
     */
    public String getVersion() {
        return DenguesCorePlugin.getDefault().getBundle().getHeaders().get(Constants.BUNDLE_VERSION).toString();
    }

    /**
     * Getter for elements.
     * 
     * @return the elements
     */
    public List<CompElement> getElements() {
        return this.elements;
    }

    public List<CompNote> getCompNotes() {
        return this.compNotes;
    }

    public void addCompNodeLabel(CompNodeLabel nodeLabel) {
        compNodeLabels.add(nodeLabel);
        elements.add(nodeLabel);
        fireStructureChange(PROP_NODELABELS, compNodeLabels);
    }

    public void removeCompNodeLabel(CompNodeLabel nodeLabel) {
        compNodeLabels.remove(nodeLabel);
        elements.remove(nodeLabel);
        fireStructureChange(PROP_NODELABELS, compNodeLabels);
    }

    public void addCompNote(CompNote note) {
        compNotes.add(note);
        elements.add(note);
        note.setCompProcess(this);
        fireStructureChange(PROP_NOTES, compNotes);
    }

    public void removeCompNote(CompNote note) {
        compNotes.remove(note);
        elements.remove(note);
        fireStructureChange(PROP_NOTES, compNotes);
    }

    public List<CompBlock> getCompBlocks() {
        return this.compBlocks;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "addCompBlock".
     * 
     * @param note
     */
    public void addCompBlock(CompBlock note) {
        compBlocks.add(note);
        elements.add(note);
        note.setCompProcess(this);
        fireStructureChange(PROP_BLOCKS, compBlocks);
    }

    public void removeCompBlock(CompBlock note) {
        compBlocks.remove(note);
        elements.remove(note);
        fireStructureChange(PROP_BLOCKS, compBlocks);
    }

    public void addCompNodeStatus(CompNodeStatus connLabel) {
        nodeStatuses.add(connLabel);
        elements.add(connLabel);
        fireStructureChange(PROP_NODE_STATUS, nodeStatuses);
    }

    public void removeCompNodeStatus(CompNodeStatus connLabel) {
        nodeStatuses.remove(connLabel);
        elements.remove(connLabel);
        fireStructureChange(PROP_NODE_STATUS, nodeStatuses);
    }

    public void addCompConnectionLabel(CompConnectionLabel connLabel) {
        connectionLabels.add(connLabel);
        elements.add(connLabel);
        fireStructureChange(PROP_CONNECTIONLABEL, connectionLabels);
    }

    public void removeCompConnectionLabel(CompConnectionLabel connLabel) {
        connectionLabels.remove(connLabel);
        elements.remove(connLabel);
        fireStructureChange(PROP_CONNECTIONLABEL, connectionLabels);
    }

    /**
     * Getter for compNodeLabels.
     * 
     * @return the compNodeLabels
     */
    public List<CompNodeLabel> getCompNodeLabels() {
        return this.compNodeLabels;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.designer.ui.process.models.CompElement#getCompProcess()
     */
    @Override
    public ICompProcess getCompProcess() {
        return this;
    }

    /**
     * Getter for connections.
     * 
     * @return the connections
     */
    public List<ICompConnection> getConnections() {
        return this.connections;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "checkProcess".
     */
    public void checkProcess() {
        for (CompNode node : getCompNodes()) {
            node.checkNode();
        }
    }

    public void addCompConnectionTrac(CompConnectionTrac connectionTrac) {
        connectionTracs.add(connectionTrac);
        elements.add(connectionTrac);
        fireStructureChange(PROP_CONNECTIONTRAC, connectionTrac);
    }

    public void removeCompConnectionTrac(CompConnectionTrac connectionTrac) {
        connectionTracs.remove(connectionTrac);
        elements.remove(connectionTrac);
        fireStructureChange(PROP_CONNECTIONTRAC, connectionTrac);
    }

    public ICompConnection findConnection(String name) {
        for (ICompConnection conn : connections) {
            if (conn.getName().equals(name)) {
                return conn;
            }
        }
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.core.process.ICompProcess#getNeededLibraries(boolean)
     */
    public Set<EMFModule> getNeededLibraries(boolean moduleUse) {
        Set<EMFModule> neededLibraries = new HashSet<EMFModule>();
        List<? extends ICompNode> nodeList = getGeneratingNodes();
        for (ICompNode compNode : nodeList) {
            List<EMFModule> modules = compNode.getComponent().getImportModules();
            for (EMFModule module : modules) {
                neededLibraries.add(module);
            }
        }
        return neededLibraries;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getGeneratingNodes".
     * 
     * @return
     */
    private List<? extends ICompNode> getGeneratingNodes() {
        return DenguesCorePlugin.getDefault().getDesignerCoreService().getGeneratingNodes(this);
    }

    public void setPurpose(String purpose) {
        this.purpose = DenguesTextUtil.getNotNullString(purpose);
    }

    public String getAuthor() {
        if (author == null) {
            author = "";
            EList<UserType> user = denguesProject.getProjectType().getUser();
            if (!user.isEmpty()) {
                author = user.get(0).getEMail();
            }
        }
        return this.author;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "changeBlockNodeColor".
     * 
     * @param rgb
     */
    public void changeBlockNodeColor(RGB rgb) {
        for (CompBlock block : compBlocks) {
            block.setColor(rgb);
        }
    }

    /**
     * Getter for isBlock.
     * 
     * @return the isBlock
     */
    public boolean isBlock() {
        return this.isBlock;
    }

    /**
     * Sets the isBlock.
     * 
     * @param isBlock the isBlock to set
     */
    public void setBlock(boolean isBlock) {
        this.isBlock = isBlock;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "addCompBlockExit".
     * 
     * @param newNote
     */
    public void addCompBlockExit(ICompBlockExit newNote) {
        newNote.setCompProcess(this);
        exits.add(newNote);
        elements.add((CompBlockExit) newNote);
        fireStructureChange(PROP_BLOCKEXITS, newNote);
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "removeCompBlockExit".
     * 
     * @param newNote
     */
    public void removeCompBlockExit(ICompBlockExit newNote) {
        exits.remove(newNote);
        elements.remove(newNote);
        fireStructureChange(PROP_BLOCKEXITS, newNote);
    }

    /**
     * Getter for exits.
     * 
     * @return the exits
     */
    public List<ICompBlockExit> getExits() {
        return this.exits;
    }
}
